package org.quipu.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import java.util.HashMap;
import java.util.Map;
import org.quipu.client.events.AppEvent;
import org.quipu.client.events.AppEventBus;
import org.quipu.client.events.AppEventListener;
import org.quipu.client.events.GotoPageEvent;
import static org.quipu.client.events.GotoPageEvent.Page.ACCOUNTS;
import static org.quipu.client.events.GotoPageEvent.Page.REPORTS;
import static org.quipu.client.events.GotoPageEvent.Page.SETTINGS;
import static org.quipu.client.events.GotoPageEvent.Page.TRANSACTIONS;
import static org.quipu.client.events.GotoPageEvent.Page.LOGIN;
import static org.quipu.client.events.GotoPageEvent.Page.USER_PROFILE;
import org.quipu.client.events.LoginEvent;
import org.quipu.dto.UserDto;

public class HeaderPanel extends AppEventWidget implements AppEventListener {

    private final HorizontalPanel hPanel;
    private final HorizontalPanel menuPanel;
    private final HorizontalPanel authPanel;
    private Label booksListLabel;
    private BookListBox booksListBox;
    private Anchor accountsLink;
    private Anchor transactionsLink;
    private Anchor settingsLink;
    private Anchor reportsLink;
    private Anchor userLoginLink;
    private Anchor signInLink;
    private Anchor signOutLink;
    private Label delimLabel;
    private Map<Anchor, HandlerRegistration> linksHandlers = new HashMap<Anchor, HandlerRegistration>();
    private Map<Anchor, GotoPageEvent.Page> pageLinks = new HashMap<Anchor, GotoPageEvent.Page>();

    public HeaderPanel(final AppEventBus eventBus, AppCache cache) {
        super(eventBus, cache);

        hPanel = new HorizontalPanel();
        hPanel.addStyleName("headerPanel");
//        hPanel.addStyleName("gridPanel");
//        hPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_JUSTIFY);
//        hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

        menuPanel = new HorizontalPanel();
        menuPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
        menuPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
        menuPanel.addStyleName("gridPanel");

        authPanel = new HorizontalPanel();
        authPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
        authPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
        authPanel.addStyleName("gridPanel");

        booksListLabel = new Label("Books:");
        booksListBox = new BookListBox(eventBus, cache, null);

        accountsLink = new Anchor("Accounts");
        pageLinks.put(accountsLink, ACCOUNTS);
        transactionsLink = new Anchor("Transactions");
        pageLinks.put(transactionsLink, TRANSACTIONS);
        settingsLink = new Anchor("Settings");
        pageLinks.put(settingsLink, SETTINGS);
        reportsLink = new Anchor("Reports");
        pageLinks.put(reportsLink, REPORTS);
        menuPanel.add(booksListLabel);
        menuPanel.add(booksListBox.getWidget());
        menuPanel.add(accountsLink);
        menuPanel.add(transactionsLink);
        menuPanel.add(settingsLink);
        menuPanel.add(reportsLink);
        
        delimLabel = new Label("|");
        userLoginLink = new Anchor("");
        pageLinks.put(userLoginLink, USER_PROFILE);
        signInLink = new Anchor("Sign in");
        pageLinks.put(signInLink, LOGIN);
        signOutLink = new Anchor("Sign out");
        pageLinks.put(signOutLink, LOGIN);
    }

    @Override
    public void init() {
        booksListBox.init();
        getEventBus().addListener(LoginEvent.class, this);
        getEventBus().addListener(GotoPageEvent.class, this);
        repaintHeader(getCache().getUser());
        updateLinks(null, getCache().getUser());
    }

    private void updateLinks(GotoPageEvent.Page currentPage, UserDto user) {
        HandlerRegistration hr;
        for(final Map.Entry<Anchor, GotoPageEvent.Page> entry: pageLinks.entrySet()) {
            hr = linksHandlers.get(entry.getKey());
            if(entry.getValue().equals(currentPage)) {
                entry.getKey().setStyleName("menu-link-selected");
                if(hr != null) {
                    hr.removeHandler();
                    linksHandlers.remove(entry.getKey());
                }
            } else {
                entry.getKey().setStyleName("menu-link-unselected");
                if(hr == null && (!entry.getKey().equals(userLoginLink) || user != null)) {
                    hr = entry.getKey().addClickHandler(new ClickHandler() {

                        @Override
                        public void onClick(ClickEvent event) {
                            if(entry.getKey().equals(signOutLink))
                                logout();
                            else
                                getEventBus().fireEvent(new GotoPageEvent(HeaderPanel.this, entry.getValue()));
                        }
                    });
                    linksHandlers.put(entry.getKey(), hr);
                }
            }
        }
    }

    @Override
    public void handleEvent(AppEvent event) {
        if(event != null) {
            if(event instanceof LoginEvent) {
                repaintHeader(getCache().getUser());
            } else if(event instanceof GotoPageEvent) {
                updateLinks(((GotoPageEvent) event).getObject(), getCache().getUser());
            }
        }
    }

    private void repaintHeader(UserDto user) {
        hPanel.clear();
        if(user != null) {
            hPanel.add(menuPanel);
        }
        authPanel.clear();
        authPanel.add(userLoginLink);
        authPanel.add(delimLabel);
        if(user == null) {
            userLoginLink.setText("Anonymous");
            authPanel.add(signInLink);
        } else {
            userLoginLink.setText(user.getLogin());
            authPanel.add(signOutLink);
        }
        hPanel.add(authPanel);
    }

    private void logout() {
        getMainService().logout(new AsyncCallback<Void>() {
            public void onFailure(Throwable caught) {
            }

            public void onSuccess(Void result) {
                getEventBus().fireEvent(new LoginEvent(HeaderPanel.this, null));
            }
        });
    }

    @Override
    public Widget getWidget() {
        return hPanel;
    }
}
